package com.niiwoo.civet.user.service.local;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.niiwoo.activity.event.constant.BizEventRabbitConstant;
import com.niiwoo.activity.event.dto.request.UserRealNameReqDTO;
import com.niiwoo.civet.account.dto.request.UserIdentityDataMQDTO;
import com.niiwoo.civet.user.dao.entity.DataStatus;
import com.niiwoo.civet.user.dao.entity.IdentityInfo;
import com.niiwoo.civet.user.dao.entity.IdentityMapping;
import com.niiwoo.civet.user.dao.entity.UserBasicInfo;
import com.niiwoo.civet.user.enums.OCRChannelEnum;
import com.niiwoo.civet.user.enums.UserDataStatusEnum;
import com.niiwoo.civet.user.enums.UserDataTypeEnum;
import com.niiwoo.civet.user.enums.UserEnum;
import com.niiwoo.civet.user.service.local.dataflow.UserDataBackFlowService;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.base.utils.IdCardUtils;
import com.niiwoo.tripod.im.component.IMService;
import com.niiwoo.tripod.im.request.UpdateUserInfoRequest;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 处理用户身份信息回调服务
 */
@Service
@Slf4j
public class UserIdentityNotifyService {


    @Autowired
    UserStatusService userStatusService;

    @Autowired
    UserIdentityService userIdentityService;

    @Autowired
    SnowflakeIdWorker snowflakeIdWorker;

    @Autowired
    IdentityMappingService identityMappingService;

    @Autowired
    PrivacyMasks privacyMasks;

    @Autowired
    private UserDataBackFlowService userDataBackFlowService;

    @Autowired
    IMService imService;

    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 初次开户同步二要素
     */
    public boolean updateStatusByOpenAccount(UserIdentityDataMQDTO dto) {

        String idCard = privacyMasks.decryptPrivacy(dto.getIdCardNo());
        String ecryptIdCardUpper = privacyMasks.encryptPrivacy(idCard.toUpperCase());

        List<DataStatus> dataStatusList = Optional.ofNullable(userStatusService.getDataStatusByUserId(dto.getUserId())).orElse(Collections.emptyList());
        // 开户
        Optional<DataStatus> oldOpenAccountStatus = dataStatusList.stream()
                                                                .filter(s -> Objects.equals(s.getDataType(), UserDataTypeEnum.BIND_BANK_CARD.getValue()))
                                                                .findFirst();
        if (oldOpenAccountStatus.isPresent() && oldOpenAccountStatus.get().getDataStatus().equals(UserDataStatusEnum.OpenBankAccountStatus.PASS_BIND.getStatus())) {
            log.info("初次开户同步二要素###开户已更新，不再重复处理, data={}", JSON.toJSONString(dto));
            return true;
        }
        DataStatus updateOpenAccountStatus = generateUpdateDataStatus(oldOpenAccountStatus, dto.getUserId(), UserDataTypeEnum.BIND_BANK_CARD.getValue(), UserDataStatusEnum.OpenBankAccountStatus.PASS_BIND.getStatus());
        //  二要素
        Optional<DataStatus> oldTwoElementStatus = dataStatusList.stream()
                                                                .filter(s -> Objects.equals(s.getDataType(), UserDataTypeEnum.TWO_ELEMENT.getValue()))
                                                                .findFirst();
        DataStatus updateTwoElementStatus = generateUpdateDataStatus(oldOpenAccountStatus, dto.getUserId(), UserDataTypeEnum.TWO_ELEMENT.getValue(), UserDataStatusEnum.RealNameAuthStatus.PASS_CERTIFIED.getStatus());
        boolean isTwoElementAuth = oldTwoElementStatus.isPresent() && Objects.equals(oldTwoElementStatus.get().getDataStatus(), UserDataStatusEnum.RealNameAuthStatus.PASS_CERTIFIED.getStatus());
        // 校验身份映射
        Optional<IdentityMapping> identityMappingOptional = Optional.ofNullable(identityMappingService.get(ecryptIdCardUpper));
        IdentityMapping updateIdentityMapping = new IdentityMapping();
        updateIdentityMapping.setIdCard(ecryptIdCardUpper);
        updateIdentityMapping.setUserId(dto.getUserId());
        if (!identityMappingOptional.isPresent()) {
            updateIdentityMapping.setCreateTime(new Date());
        }
        // 身份信息，以存管为准
        Optional<IdentityInfo> oldIdentityInfoOpt = Optional.ofNullable(userIdentityService.getByUserId(dto.getUserId()));
        IdentityInfo updateIdentityInfo = new IdentityInfo();
        updateIdentityInfo.setUserId(dto.getUserId());
        updateIdentityInfo.setBirthday(IdCardUtils.getBirthdayByIdCard(idCard));

        UserEnum.Gender gender = Integer.valueOf(idCard.substring(16, 17)) % 2 == 0 ? UserEnum.Gender.FEMALE : UserEnum.Gender.MALE;
        if (!isTwoElementAuth) {
            updateIdentityInfo.setName(dto.getName());
            updateIdentityInfo.setIdCard(ecryptIdCardUpper);
            updateIdentityInfo.setSex(Integer.valueOf(gender.getValue()).byteValue());
            updateIdentityInfo.setAddressCode(idCard.substring(0, 6));
        }
        updateIdentityInfo.setUpdateTime(new Date());
        if (!oldIdentityInfoOpt.isPresent()) {
            updateIdentityInfo.setCreateTime(new Date());
            updateIdentityInfo.setNation("");
            updateIdentityInfo.setAddress("");
            updateIdentityInfo.setSigningAuthority("");
            updateIdentityInfo.setOcrChannel(OCRChannelEnum.EMPTY.getValue());
        }
        // 如果已存在且认证通过，则判断身份信息与开户的姓名、身份证号是否一致，以存管为准

        boolean isMatch = !isTwoElementAuth || (oldIdentityInfoOpt.isPresent() && oldIdentityInfoOpt.get().getName().equals(dto.getName()) && oldIdentityInfoOpt.get().getIdCard().equalsIgnoreCase(dto.getIdCardNo()));
        //  OCR, 存在则更新状态
        Optional<DataStatus> updateOCRStatusOpt = dataStatusList.stream()
                                                                .filter(s -> Objects.equals(s.getDataType(), UserDataTypeEnum.OCR.getValue()))
                                                                .findFirst()
                                                                .filter(s -> !isMatch)
                                                                .map(s -> generateUpdateDataStatus(Optional.of(s), s.getUserId(), s.getDataType(), UserDataStatusEnum.OCRStatus.NOT_OCR.getStatus()));
        //  肖像认证, 存在则更新状态
        Optional<DataStatus> updatePortraitStatusOpt = dataStatusList.stream()
                                                                    .filter(s -> Objects.equals(s.getDataType(), UserDataTypeEnum.PORTRAIT.getValue()))
                                                                    .findFirst()
                                                                    .filter(s -> !isMatch)
                                                                    .map(s -> generateUpdateDataStatus(Optional.of(s), s.getUserId(), s.getDataType(), UserDataStatusEnum.PortraitAuthStatus.NOT_PASS.getStatus()));
        // 修改性别
        UserBasicInfo basicInfo = null;
        if (!isTwoElementAuth) {
            basicInfo = new UserBasicInfo();
            basicInfo.setUserId(dto.getUserId());
            basicInfo.setGender(Integer.valueOf(gender.getValue()).byteValue());
        }
        boolean isUpdateSuccess =  userIdentityService.updateAuthInfoByOpenAccount(
                                                                                    oldOpenAccountStatus.isPresent(), updateOpenAccountStatus,
                                                                                    oldTwoElementStatus.isPresent(), updateTwoElementStatus,
                                                                                    identityMappingOptional.isPresent(), updateIdentityMapping,
                                                                                    oldIdentityInfoOpt.isPresent(), updateIdentityInfo,
                                                                                    basicInfo,
                                                                                    updateOCRStatusOpt,
                                                                                    updatePortraitStatusOpt
                                                                                    );
        if (isUpdateSuccess) {

            UserRealNameReqDTO json = new UserRealNameReqDTO();
            json.setUserId(dto.getUserId());
            json.setIdentityCard(privacyMasks.encryptPrivacy(idCard.toUpperCase()));
            json.setRealNameDate(new Date());
            json.setUpdateDate(new Date());
            log.info("首次开户成功###标签-实名认证, data={}", JSONObject.toJSONString(json));
            rabbitTemplate.convertAndSend(BizEventRabbitConstant.Exchange.BIZ_EVENT_DIRECT_EXCHANGE, BizEventRabbitConstant.Key.BIZ_EVENT_USER_REAL_NAME_KEY, json);

            UpdateUserInfoRequest imRequest = new UpdateUserInfoRequest();
            imRequest.setGuid(dto.getUserId());
            imRequest.setAddIdentity(1);
            imRequest.setGender(Integer.valueOf(gender.getValue()).byteValue());
            log.info("首次开户成功###调用IM###请求， request={}", JSON.toJSONString(imRequest));
            CompletableFuture.runAsync(() -> imService.updateUserInfo(imRequest));

            //个人实名信息回流
            userDataBackFlowService.identityRealInfoBackFlow(dto.getUserId());
        }
        return isUpdateSuccess;
    }

    private DataStatus generateUpdateDataStatus(Optional<DataStatus> oldDataStatusOpt, String userId, byte dataType, byte status) {
        DataStatus updateStatus = new DataStatus();
        updateStatus.setUserId(userId);
        updateStatus.setDataType(dataType);
        updateStatus.setDataStatus(status);
        updateStatus.setAuthTime(new Date());
        if (!oldDataStatusOpt.isPresent()) {
            updateStatus.setId(snowflakeIdWorker.nextId());
            updateStatus.setCreateTime(new Date());
        }
        return updateStatus;
    }

}
